1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.math;
18
19 import static com.google.common.base.Preconditions.checkNotNull;
20 import static com.google.common.math.MathPreconditions.checkNoOverflow;
21 import static com.google.common.math.MathPreconditions.checkNonNegative;
22 import static com.google.common.math.MathPreconditions.checkPositive;
23 import static com.google.common.math.MathPreconditions.checkRoundingUnnecessary;
24 import static java.lang.Math.abs;
25 import static java.lang.Math.min;
26 import static java.math.RoundingMode.HALF_EVEN;
27 import static java.math.RoundingMode.HALF_UP;
28
29 import com.google.common.annotations.GwtCompatible;
30 import com.google.common.annotations.VisibleForTesting;
31
32 import java.math.RoundingMode;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 @GwtCompatible(emulated = true)
49 public final class IntMath {
50
51
52
53
54
55
56
57
58
59 public static boolean isPowerOfTwo(int x) {
60 return x > 0 & (x & (x - 1)) == 0;
61 }
62
63
64
65
66
67
68 @VisibleForTesting
69 static int lessThanBranchFree(int x, int y) {
70
71
72 return ~~(x - y) >>> (Integer.SIZE - 1);
73 }
74
75
76
77
78
79
80
81
82 @SuppressWarnings("fallthrough")
83
84 public static int log2(int x, RoundingMode mode) {
85 checkPositive("x", x);
86 switch (mode) {
87 case UNNECESSARY:
88 checkRoundingUnnecessary(isPowerOfTwo(x));
89
90 case DOWN:
91 case FLOOR:
92 return (Integer.SIZE - 1) - Integer.numberOfLeadingZeros(x);
93
94 case UP:
95 case CEILING:
96 return Integer.SIZE - Integer.numberOfLeadingZeros(x - 1);
97
98 case HALF_DOWN:
99 case HALF_UP:
100 case HALF_EVEN:
101
102 int leadingZeros = Integer.numberOfLeadingZeros(x);
103 int cmp = MAX_POWER_OF_SQRT2_UNSIGNED >>> leadingZeros;
104
105 int logFloor = (Integer.SIZE - 1) - leadingZeros;
106 return logFloor + lessThanBranchFree(cmp, x);
107
108 default:
109 throw new AssertionError();
110 }
111 }
112
113
114 @VisibleForTesting static final int MAX_POWER_OF_SQRT2_UNSIGNED = 0xB504F333;
115
116 private static int log10Floor(int x) {
117
118
119
120
121
122
123
124 int y = maxLog10ForLeadingZeros[Integer.numberOfLeadingZeros(x)];
125
126
127
128
129 return y - lessThanBranchFree(x, powersOf10[y]);
130 }
131
132
133 @VisibleForTesting static final byte[] maxLog10ForLeadingZeros = {9, 9, 9, 8, 8, 8,
134 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0};
135
136 @VisibleForTesting static final int[] powersOf10 = {1, 10, 100, 1000, 10000,
137 100000, 1000000, 10000000, 100000000, 1000000000};
138
139
140 @VisibleForTesting static final int[] halfPowersOf10 =
141 {3, 31, 316, 3162, 31622, 316227, 3162277, 31622776, 316227766, Integer.MAX_VALUE};
142
143 private static int sqrtFloor(int x) {
144
145
146 return (int) Math.sqrt(x);
147 }
148
149
150
151
152
153
154
155
156 @SuppressWarnings("fallthrough")
157 public static int divide(int p, int q, RoundingMode mode) {
158 checkNotNull(mode);
159 if (q == 0) {
160 throw new ArithmeticException("/ by zero");
161 }
162 int div = p / q;
163 int rem = p - q * div;
164
165 if (rem == 0) {
166 return div;
167 }
168
169
170
171
172
173
174
175
176 int signum = 1 | ((p ^ q) >> (Integer.SIZE - 1));
177 boolean increment;
178 switch (mode) {
179 case UNNECESSARY:
180 checkRoundingUnnecessary(rem == 0);
181
182 case DOWN:
183 increment = false;
184 break;
185 case UP:
186 increment = true;
187 break;
188 case CEILING:
189 increment = signum > 0;
190 break;
191 case FLOOR:
192 increment = signum < 0;
193 break;
194 case HALF_EVEN:
195 case HALF_DOWN:
196 case HALF_UP:
197 int absRem = abs(rem);
198 int cmpRemToHalfDivisor = absRem - (abs(q) - absRem);
199
200
201 if (cmpRemToHalfDivisor == 0) {
202 increment = (mode == HALF_UP || (mode == HALF_EVEN & (div & 1) != 0));
203 } else {
204 increment = cmpRemToHalfDivisor > 0;
205 }
206 break;
207 default:
208 throw new AssertionError();
209 }
210 return increment ? div + signum : div;
211 }
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229 public static int mod(int x, int m) {
230 if (m <= 0) {
231 throw new ArithmeticException("Modulus " + m + " must be > 0");
232 }
233 int result = x % m;
234 return (result >= 0) ? result : result + m;
235 }
236
237
238
239
240
241
242
243 public static int gcd(int a, int b) {
244
245
246
247
248
249 checkNonNegative("a", a);
250 checkNonNegative("b", b);
251 if (a == 0) {
252
253
254 return b;
255 } else if (b == 0) {
256 return a;
257 }
258
259
260
261
262 int aTwos = Integer.numberOfTrailingZeros(a);
263 a >>= aTwos;
264 int bTwos = Integer.numberOfTrailingZeros(b);
265 b >>= bTwos;
266 while (a != b) {
267
268
269
270
271
272
273
274 int delta = a - b;
275
276 int minDeltaOrZero = delta & (delta >> (Integer.SIZE - 1));
277
278
279 a = delta - minDeltaOrZero - minDeltaOrZero;
280
281
282 b += minDeltaOrZero;
283 a >>= Integer.numberOfTrailingZeros(a);
284 }
285 return a << min(aTwos, bTwos);
286 }
287
288
289
290
291
292
293 public static int checkedAdd(int a, int b) {
294 long result = (long) a + b;
295 checkNoOverflow(result == (int) result);
296 return (int) result;
297 }
298
299
300
301
302
303
304 public static int checkedSubtract(int a, int b) {
305 long result = (long) a - b;
306 checkNoOverflow(result == (int) result);
307 return (int) result;
308 }
309
310
311
312
313
314
315 public static int checkedMultiply(int a, int b) {
316 long result = (long) a * b;
317 checkNoOverflow(result == (int) result);
318 return (int) result;
319 }
320
321
322
323
324
325
326
327
328
329 public static int checkedPow(int b, int k) {
330 checkNonNegative("exponent", k);
331 switch (b) {
332 case 0:
333 return (k == 0) ? 1 : 0;
334 case 1:
335 return 1;
336 case (-1):
337 return ((k & 1) == 0) ? 1 : -1;
338 case 2:
339 checkNoOverflow(k < Integer.SIZE - 1);
340 return 1 << k;
341 case (-2):
342 checkNoOverflow(k < Integer.SIZE);
343 return ((k & 1) == 0) ? 1 << k : -1 << k;
344 default:
345
346 }
347 int accum = 1;
348 while (true) {
349 switch (k) {
350 case 0:
351 return accum;
352 case 1:
353 return checkedMultiply(accum, b);
354 default:
355 if ((k & 1) != 0) {
356 accum = checkedMultiply(accum, b);
357 }
358 k >>= 1;
359 if (k > 0) {
360 checkNoOverflow(-FLOOR_SQRT_MAX_INT <= b & b <= FLOOR_SQRT_MAX_INT);
361 b *= b;
362 }
363 }
364 }
365 }
366
367 @VisibleForTesting static final int FLOOR_SQRT_MAX_INT = 46340;
368
369
370
371
372
373
374
375
376 public static int factorial(int n) {
377 checkNonNegative("n", n);
378 return (n < factorials.length) ? factorials[n] : Integer.MAX_VALUE;
379 }
380
381 private static final int[] factorials = {
382 1,
383 1,
384 1 * 2,
385 1 * 2 * 3,
386 1 * 2 * 3 * 4,
387 1 * 2 * 3 * 4 * 5,
388 1 * 2 * 3 * 4 * 5 * 6,
389 1 * 2 * 3 * 4 * 5 * 6 * 7,
390 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8,
391 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9,
392 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10,
393 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11,
394 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12};
395
396
397 @VisibleForTesting static int[] biggestBinomials = {
398 Integer.MAX_VALUE,
399 Integer.MAX_VALUE,
400 65536,
401 2345,
402 477,
403 193,
404 110,
405 75,
406 58,
407 49,
408 43,
409 39,
410 37,
411 35,
412 34,
413 34,
414 33
415 };
416
417
418
419
420
421
422
423 public static int mean(int x, int y) {
424
425
426
427 return (x & y) + ((x ^ y) >> 1);
428 }
429
430 private IntMath() {}
431 }
432